package cn.maihe.elg.operation.centers.epoint.handler.service;

import cn.maihe.elg.operation.centers.epoint.auth.EpointCenterAuthConfig;
import cn.maihe.elg.operation.centers.epoint.config.EpointCenterInfosConfig;
import cn.maihe.elg.operation.centers.epoint.dto.EpointBaseRespDTO;
import cn.maihe.elg.operation.centers.epoint.dto.handler.MeiShanApplyData;
import cn.maihe.elg.operation.centers.epoint.dto.handler.MeiShanApplyGuaranteeReq;
import cn.maihe.elg.operation.centers.epoint.dto.handler.MeiShanApplyGuaranteeResp;
import cn.maihe.elg.operation.centers.epoint.dto.handler.MeiShanApplyGuaranteeRespData;
import cn.maihe.elg.operation.centers.epoint.dto.handler.MeiShanProjectInfoDecryptionVo;
import cn.maihe.elg.operation.centers.epoint.enums.EpointRespCodeEnum;
import cn.maihe.elg.operation.centers.epoint.exception.EpointException;
import cn.maihe.elg.operation.centers.epoint.handler.EpointCenterTradeService;
import cn.maihe.elg.operation.centers.supports.CenterTradeContext;
import cn.maihe.elg.operation.centers.supports.annotation.CenterTradeService;
import cn.maihe.elg.operation.exception.CenterException;
import cn.maihe.elg.operation.model.bo.AcceptOrderBO;
import cn.maihe.elg.operation.model.bo.ApplyTemplatePdfParams;
import cn.maihe.elg.operation.model.enums.AcceptOrderStatus;
import cn.maihe.elg.operation.model.enums.AttachmentFileType;
import cn.maihe.elg.operation.model.enums.CenterNoEnum;
import cn.maihe.elg.operation.model.enums.CenterProviderEnum;
import cn.maihe.elg.operation.model.enums.GuaranteeCategory;
import cn.maihe.elg.operation.model.enums.GuaranteeTemplateType;
import cn.maihe.elg.operation.model.enums.GuaranteeType;
import cn.maihe.elg.operation.model.enums.IDType;
import cn.maihe.elg.operation.model.enums.InstitutionOrgCodeEnum;
import cn.maihe.elg.operation.model.enums.TradeType;
import cn.maihe.elg.operation.model.enums.UserStatusEnum;
import cn.maihe.elg.operation.model.enums.UserType;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.BidCustomerDO;
import cn.maihe.elg.operation.repository.entity.GuaranteeInstitutionDO;
import cn.maihe.elg.operation.repository.entity.ProjectInfoDO;
import cn.maihe.elg.operation.repository.entity.UserDO;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.GuaranteeAttachmentInfoService;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.utils.DateUtils;
import cn.maihe.elg.operation.supports.system.ElgResourceService;
import cn.maihe.elg.operation.supports.bank.cmb.util.CashServiceUtil;
import cn.maihe.elg.operation.utils.DateUtil;
import cn.maihe.elg.operation.utils.IdGenerate;
import cn.maihe.elg.operation.utils.SM4Util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ggy.encrypttools.sm.SMUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.time.Instant;
import java.util.Date;
import java.util.Objects;

/**
 * @Description 投保申请
 * @Author SSX
 * @Date 2025/05/28
 */
@CenterTradeService(
        provider = CenterProviderEnum.EPOINT,
        centerNo = CenterNoEnum.MEISHAN,
        tradeType = TradeType.baohanapply,
        reqClass = MeiShanApplyGuaranteeReq.class,
        respClass = EpointBaseRespDTO.class
)
@Slf4j
public class MeiShanBaohanApplyService extends EpointCenterTradeService<MeiShanApplyGuaranteeReq, MeiShanApplyGuaranteeResp> {
    public MeiShanBaohanApplyService(EpointCenterInfosConfig centerInfosConfig) {
        super(centerInfosConfig);
    }

    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;

    @Resource
    private ElgResourceService elgResourceService;

    @Resource
    private GuaranteeAttachmentInfoService guaranteeAttachmentInfoService;

    @Value("${cn.maihe.elg.operation.common-secret-key.publicKey}")
    private String publicKey;

    @Value("${cn.maihe.elg.operation.common-secret-key.privateKey}")
    private String privateKey;

    @Value("${cn.maihe.elg.bank.cmb-bank.transaction-manager.auto-create-subAccount:false}")
    private Boolean autoCreateSubAccount;

    @Override
    protected void verifyParam(CenterTradeContext<MeiShanApplyGuaranteeReq, MeiShanApplyGuaranteeResp> context) {
        super.verifyParam(context);
        MeiShanApplyGuaranteeReq req = context.getReq();
        String orderNo = req.getApplyno();
        boolean exists = acceptOrderInfoService.existsCenterOrderId(context.getCenterId(), orderNo);
        Assert.isTrue(!exists, () -> "中心订单编号已存在");
    }

    @Override
    public MeiShanApplyGuaranteeResp processService(CenterTradeContext<MeiShanApplyGuaranteeReq, MeiShanApplyGuaranteeResp> context) {
        AcceptOrderInfoDO acceptOrderInfoDO = buildAcceptOrderInfo(context);
       return buildResp(acceptOrderInfoDO);
    }

    private AcceptOrderInfoDO buildAcceptOrderInfo(CenterTradeContext<MeiShanApplyGuaranteeReq, MeiShanApplyGuaranteeResp> context) {
        MeiShanApplyGuaranteeReq req = context.getReq();
        long centerId = context.getCenterId();
        long orgId = context.getOrgId();
        InstitutionOrgCodeEnum institutionOrgCodeEnum = InstitutionOrgCodeEnum.resolve(context.getOrgCode());
        GuaranteeInstitutionDO institutionDO = getInstitutionIdByCode(institutionOrgCodeEnum);
        String acceptOrderNo = IdGenerate.genAcceptOrderNo(context.getCenterNoEnum());

        String subAccount = null;
        if(!autoCreateSubAccount){
            subAccount = DateUtils.format(new Date(), "MMddHHmmss");
        }

        subAccount = CashServiceUtil.subAccountCreateResult(subAccount);
        if(StringUtils.isBlank(subAccount)){
            throw new RuntimeException("记账子单元创建异常");
        }

        JSONObject ciphertext = new JSONObject();
        ciphertext.put("applydata",req.getApplydata());
        ciphertext.put("digitalenvelope",req.getDigitalenvelope());

        AcceptOrderInfoDO curAcceptOrder = AcceptOrderInfoDO.builder()
                .centerId(centerId).orgId(orgId)
                .guaranteeNo(IdGenerate.genGuaranteeNo(institutionDO.getInstitutionCode()))
                .centerOrderId(req.getApplyno())
                .centerOrderTime(DateUtil.getDatetime())
                .acceptOrderNo(acceptOrderNo)
                .institutionId(institutionDO.getId())
                .ciphertext(ciphertext.toJSONString())
                .subAccount(subAccount)
                .clientId(req.getPlatformcode())
                .status(AcceptOrderStatus.WAIT_PAY.getStatus())
                .build();

        return acceptOrderInfoService.saveOrUpdateAcceptOrderInfo(curAcceptOrder);
    }

    private MeiShanApplyGuaranteeResp buildResp(AcceptOrderInfoDO acceptOrderInfoDO) {
        MeiShanApplyGuaranteeResp resp = EpointBaseRespDTO.success("受理成功", MeiShanApplyGuaranteeResp.class);
        MeiShanApplyGuaranteeRespData meiShanApplyGuaranteeRespData = new MeiShanApplyGuaranteeRespData();
        String acceptOrderNoCiphertext = Base64.encodeBase64String(SMUtils.encryptBySM2(acceptOrderInfoDO.getAcceptOrderNo(), publicKey).getBytes(StandardCharsets.UTF_8));
        meiShanApplyGuaranteeRespData.setRedirecturl(elgResourceService.buildElgFrontUrl("/#/applyOrderDecryption?ordersn=" + acceptOrderNoCiphertext));
        resp.setData(meiShanApplyGuaranteeRespData);
        return resp;
    }

    public String getAcceptOrderNoPlaintext(String acceptOrderNoCiphertext) {
        return SMUtils.decryptBySM2(new String(Base64.decodeBase64(acceptOrderNoCiphertext)),privateKey);
    }

    /**
     *
     * @param acceptOrderNoCiphertext 受理订单号（密文）
     * @param digitalenvelopePlaintext 数字信封（明文）
     * @param decryptionType 解密类型 1：标正通 ,2:全国CA互认,3：介质CA
     * @return
     */
    public MeiShanApplyGuaranteeResp baohanApply(String acceptOrderNoCiphertext,String digitalenvelopePlaintext,String decryptionType) {
        String acceptOrderNo = getAcceptOrderNoPlaintext(acceptOrderNoCiphertext);
        log.info("baohanApply acceptOrderNo:{}",acceptOrderNo);

        AcceptOrderInfoDO acceptOrderInfoDO = acceptOrderInfoService.getByAcceptOrderNo(acceptOrderNo);
        if(Objects.isNull(acceptOrderInfoDO)){
            throw EpointException.of(EpointRespCodeEnum.FAILURE, "查无此受理订单信息");
        }
        
        AcceptOrderBO acceptOrderBO = this.parseApplyGuaranteeInfo(acceptOrderInfoDO, digitalenvelopePlaintext, decryptionType);

        acceptOrderInfoService.saveAcceptOrderBO(acceptOrderBO);

        return buildResp(acceptOrderBO);
    }

    private MeiShanApplyGuaranteeResp buildResp(AcceptOrderBO acceptOrderBO) {
       MeiShanApplyGuaranteeResp resp = EpointBaseRespDTO.success("受理成功", MeiShanApplyGuaranteeResp.class);
        MeiShanApplyGuaranteeRespData meiShanApplyGuaranteeRespData = new MeiShanApplyGuaranteeRespData();
        meiShanApplyGuaranteeRespData.setRedirecturl(elgResourceService.buildElgFrontUrl("/#/autoLogin?mobile=" + acceptOrderBO.getUserDO().getUsername() + "&ordersn=" + acceptOrderBO.getAcceptOrderInfo().getAcceptOrderNo()));
        log.info("MeiShanBaohanApplyService payurl:{}",meiShanApplyGuaranteeRespData.getRedirecturl());
        resp.setData(meiShanApplyGuaranteeRespData);
        //跳转到该订单上传申请书&反担保协议书 及 支付凭证页面
        makeAndSaveApplyFile(acceptOrderBO);
        return resp;
    }

    /**
     * docx模板合成申请书
     */
    private void makeAndSaveApplyFile(AcceptOrderBO acceptOrderBO) {
        ApplyTemplatePdfParams params = new ApplyTemplatePdfParams();
        params.setBidderName(acceptOrderBO.getBidCustomer().getBidderName());
        params.setProjectName(acceptOrderBO.getProjectInfo().getProjectName());
        Triple<String, String, String> triple = DateUtil.parseLocalDate();
        params.setYear(triple.getLeft());
        params.setMonth(triple.getMiddle());
        params.setDay(triple.getRight());
        AcceptOrderInfoDO orderInfo = acceptOrderBO.getAcceptOrderInfo();
        String acceptOrderNo = orderInfo.getAcceptOrderNo();
        Path docxPath = elgResourceService.buildApplyFileByTemplate(acceptOrderNo, params);

        guaranteeAttachmentInfoService.saveOrUpdateAttachmentInfo(orderInfo, docxPath, AttachmentFileType.TYPE_12, "申请书未签章");

    }

    /**
     * 解析 受理的清单信息
     */
    private AcceptOrderBO parseApplyGuaranteeInfo(AcceptOrderInfoDO acceptOrderInfo,String digitalenvelopePlaintext,String decryptionType) {
        EpointCenterAuthConfig authConfig;
        try {
            authConfig = this.getAuthConfig(centerNoEnum);
        } catch (Exception e) {
            throw EpointException.of(EpointRespCodeEnum.FAILURE, "参数未配置:" + e.getMessage(), e);
        }
        
        JSONObject ciphertext = JSON.parseObject(acceptOrderInfo.getCiphertext());
        String applydataCiphertext = ciphertext.getString("applydata");
        String applydataPlaintext;
        try {
            applydataPlaintext = new String(SM4Util.decrypt_ECB_Padding(Base64.decodeBase64(digitalenvelopePlaintext), Base64.decodeBase64(applydataCiphertext)), StandardCharsets.UTF_8);
            log.info("MeiShanBaohanApplyService applydataPlaintext:{}",JSON.toJSONString(applydataPlaintext));
        } catch (Exception e) {
            log.info("MeiShanBaohanApplyService applydataCiphertext 解密失败");
            throw CenterException.exception("解密失败",e);
        }
        MeiShanApplyData applyData = JSON.parseObject(applydataPlaintext,MeiShanApplyData.class);

        GuaranteeInstitutionDO institutionDO = getGuaranteeInstitutionByInstitutionId(acceptOrderInfo.getInstitutionId());

        CenterTradeContext context = buildCenterTradeContext(new MeiShanApplyGuaranteeReq(), centerNoEnum, institutionDO.getInstitutionCode(), null);
        context.setAttr(authConfigKey, authConfig);

        long centerId = context.getCenterId();
        long orgId = context.getOrgId();

        ProjectInfoDO projectInfoDO = this.buildProjectInfo(applyData, centerId, orgId, decryptionType);
        BidCustomerDO bidCustomerDO = this.buildBidCustomerInfo(applyData, centerId, orgId);
        UserDO userDO = this.buildUserInfo(applyData, centerId, orgId);
        AcceptOrderInfoDO acceptOrderInfoDO = this.buildAcceptOrderInfo(acceptOrderInfo, applyData);

        //计算保费
        String feeRate = this.getCurCenterInfo(context).getFeeRate();
        acceptOrderInfoDO.setFeeRate(feeRate);
        String minFeeYuan = this.getCurCenterInfo(context).getMinFeeYuan();
        acceptOrderInfoDO.setGuaranteeFee(this.calcGuaranteeFee(projectInfoDO.getBidBond(), feeRate, minFeeYuan));

        AcceptOrderBO orderBO = AcceptOrderBO.builder().centerId(centerId).orgId(orgId)
                .acceptOrderInfo(acceptOrderInfoDO).projectInfo(projectInfoDO).bidCustomer(bidCustomerDO).userDO(userDO).build();
        //默认投标保函类别;
        orderBO.setGuaranteeCategory(GuaranteeCategory.BID);
        //默认担保公司担保类型;
        orderBO.setGuaranteeType(GuaranteeType.GUARANTEE);
        InstitutionOrgCodeEnum institutionOrgCodeEnum = InstitutionOrgCodeEnum.resolve(context.getOrgCode());
        orderBO.setInstitutionOrgCodeEnum(institutionOrgCodeEnum);
        orderBO.setIsInnerApply(false);

        acceptOrderInfoDO.setGuaranteeType(orderBO.getGuaranteeType().getTypeStr());
        acceptOrderInfoDO.setGuaranteeCategory(orderBO.getGuaranteeCategory().getCategoryStr());
        return orderBO;
    }


    private AcceptOrderInfoDO buildAcceptOrderInfo(AcceptOrderInfoDO acceptOrderInfoDO, MeiShanApplyData applyData) {
        acceptOrderInfoDO.setBidCustomerName(applyData.getBiddername());
        acceptOrderInfoDO.setSectionName(applyData.getBiaoduanname());
        return acceptOrderInfoDO;
    }

    private BidCustomerDO buildBidCustomerInfo(MeiShanApplyData applyData,long centerId, long orgId) {
        return BidCustomerDO.builder()
                .centerId(centerId).orgId(orgId)
                .bidderName(applyData.getBiddername())
                .bidderCreditCode(applyData.getBiddercode())
                .bidderContactIdcardType(IDType.ID_CARD.getType())
                .legalPersonIdcardType(IDType.ID_CARD.getType())
                .enableAutoApprove(0) //'是否自动审批 0否 1是'
                .blacklistFlag(0) //'是否黑名单 0否 1是'
                .gmtCreate(Date.from(Instant.now())).build();

    }

    private UserDO buildUserInfo(MeiShanApplyData applyData,long centerId, long orgId) {
        return UserDO.builder()
                .umLogin("0")
                .followId(applyData.getBiddercode())
                .username(applyData.getBiddercode())
                .mobileNo(null)//改成统一社会信用代码登录
                .name(applyData.getBiddername())
                .type(UserType.BIDDER.getType())
                .status(UserStatusEnum.NORMAL.name())
                .orgCode("-1")
                .gmtCreate(new Date())
                .gmtModified(new Date())
                .build();
    }

    private ProjectInfoDO buildProjectInfo(MeiShanApplyData applyData,long centerId, long orgId,String decryptionType) {
        JSONObject ciphertext = new JSONObject();
        MeiShanProjectInfoDecryptionVo meiShanProjectInfoDecryptionVo = MeiShanProjectInfoDecryptionVo.builder()
                .sectionCode(applyData.getBiaoduanno())
                .sectionName(applyData.getBiaoduanname())
                .tenderer(applyData.getZbr())
                .tendererCreditCode(applyData.getZbrorgnum())
                .tendererContact(applyData.getInsuredcontactname())
                .tendererContactTel(applyData.getInsuredcontactphone())
                .tendererAddress(applyData.getInsuredaddress())
                .bzjenddate(applyData.getBzjenddate())
                .build();
        ciphertext.put("meiShanProjectInfoDecryptionVo",JSON.toJSONString(meiShanProjectInfoDecryptionVo));
        ciphertext.put("decryptionType",decryptionType);

        return ProjectInfoDO.builder()
                .centerId(centerId).orgId(orgId)
                .sectionCode(applyData.getBiaoduanno()) // 密文
                .sectionName(applyData.getBiaoduanname()) // 密文
                .bidBond(yuan2fenLong(applyData.getBzjamount()))
                .tenderer(applyData.getZbr()) // 密文
                .tendererCreditCode(applyData.getZbrorgnum()) // 密文
                .tendererContact(applyData.getInsuredcontactname())// 密文
                .tendererContactTel(applyData.getInsuredcontactphone())// 密文
                .tendererAddress(applyData.getInsuredaddress())// 密文
                .ciphertext(ciphertext.toJSONString()) // 密文
                .templateId(GuaranteeTemplateType.meishanGuaranteeTemplate.getTemplateId())
                .projectEncryptionFlag(1)
                .warnFlag(0)// '预警标识0正常 1出函机构无法受理该项目',
                .sourceFlag(0)// '信息来源0自动 1手动',
                .gmtCreate(Date.from(Instant.now()))
                .build();
    }

}
